function recommendation_system()
% RECOMMENDATION_SYSTEM 基于SVD的推荐系统专项实验
% 
% 深入研究SVD在协同过滤推荐系统中的应用

fprintf('=== 基于SVD的推荐系统专项实验 ===\n\n');

%% 实验1：基础协同过滤
fprintf('实验1：基础协同过滤\n');
fprintf('目标：理解基于SVD的协同过滤基本原理\n\n');

% 创建模拟用户-物品评分矩阵
n_users = 50;
n_items = 30;
n_factors = 5;  % 潜在因子数

% 生成潜在因子模型
rng(42);  % 固定随机种子
user_factors = randn(n_users, n_factors);
item_factors = randn(n_items, n_factors);

% 真实评分矩阵（完整的）
ratings_true = user_factors * item_factors' + 3;  % 基础评分3分
ratings_true = max(1, min(5, ratings_true));  % 限制在1-5分范围

% 模拟稀疏观测（只有部分评分可见）
observation_rate = 0.2;  % 20%的评分被观测
mask = rand(n_users, n_items) < observation_rate;
ratings_observed = ratings_true;
ratings_observed(~mask) = 0;  % 未观测的设为0

fprintf('推荐系统数据信息:\n');
fprintf('用户数量: %d\n', n_users);
fprintf('物品数量: %d\n', n_items);
fprintf('总评分数: %d\n', n_users * n_items);
fprintf('观测评分数: %d (%.1f%%)\n', sum(mask(:)), 100 * observation_rate);
fprintf('评分范围: [%.1f, %.1f]\n', min(ratings_true(:)), max(ratings_true(:)));

% 计算基本统计
observed_ratings = ratings_observed(mask);
fprintf('观测评分统计:\n');
fprintf('平均评分: %.2f\n', mean(observed_ratings));
fprintf('评分标准差: %.2f\n', std(observed_ratings));

%% 实验2：简单SVD方法
fprintf('\n实验2：简单SVD方法\n');
fprintf('目标：使用基本SVD进行矩阵补全\n\n');

% 方法1：将缺失值填充为全局均值
global_mean = mean(observed_ratings);
ratings_filled = ratings_observed;
ratings_filled(~mask) = global_mean;

fprintf('简单填充策略:\n');
fprintf('全局均值填充: %.2f\n', global_mean);

% SVD分解
[U1, S1, V1] = svd(ratings_filled);
singular_values = diag(S1);

fprintf('奇异值分析:\n');
fprintf('前10个奇异值: [%.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f]\n', ...
        singular_values(1:10));

% 不同秩的近似
ranks_test = [2, 5, 10, 15, 20];
fprintf('\n不同秩近似的效果:\n');
fprintf('秩    训练RMSE    测试RMSE    覆盖率\n');
fprintf('--    ---------    --------    ------\n');

for r = ranks_test
    % 低秩近似
    ratings_pred = U1(:, 1:r) * S1(1:r, 1:r) * V1(:, 1:r)';
    ratings_pred = max(1, min(5, ratings_pred));  % 限制评分范围
    
    % 训练误差（观测数据）
    train_rmse = sqrt(mean((ratings_pred(mask) - ratings_true(mask)).^2));
    
    % 测试误差（未观测数据）
    test_rmse = sqrt(mean((ratings_pred(~mask) - ratings_true(~mask)).^2));
    
    % 覆盖率（能够推荐的物品比例）
    coverage = mean(any(ratings_pred > 0, 1));
    
    fprintf('%2d    %9.4f    %8.4f    %6.2f\n', r, train_rmse, test_rmse, coverage);
end

%% 实验3：改进的SVD方法
fprintf('\n实验3：改进的SVD方法\n');
fprintf('目标：使用更好的填充策略改进SVD\n\n');

% 方法2：用户和物品偏置填充
user_means = zeros(n_users, 1);
item_means = zeros(n_items, 1);

% 计算用户平均评分
for u = 1:n_users
    user_ratings = ratings_observed(u, mask(u, :));
    if ~isempty(user_ratings)
        user_means(u) = mean(user_ratings);
    else
        user_means(u) = global_mean;
    end
end

% 计算物品平均评分
for i = 1:n_items
    item_ratings = ratings_observed(mask(:, i), i);
    if ~isempty(item_ratings)
        item_means(i) = mean(item_ratings);
    else
        item_means(i) = global_mean;
    end
end

fprintf('偏置统计:\n');
fprintf('用户评分均值范围: [%.2f, %.2f]\n', min(user_means), max(user_means));
fprintf('物品评分均值范围: [%.2f, %.2f]\n', min(item_means), max(item_means));

% 偏置填充
ratings_bias_filled = ratings_observed;
for u = 1:n_users
    for i = 1:n_items
        if ~mask(u, i)
            % 使用用户偏置和物品偏置的组合
            ratings_bias_filled(u, i) = (user_means(u) + item_means(i)) / 2;
        end
    end
end

% 偏置填充的SVD
[U2, S2, V2] = svd(ratings_bias_filled);

fprintf('\n偏置填充SVD结果:\n');
fprintf('秩    训练RMSE    测试RMSE    改善程度\n');
fprintf('--    ---------    --------    --------\n');

for r = ranks_test
    % 低秩近似
    ratings_pred2 = U2(:, 1:r) * S2(1:r, 1:r) * V2(:, 1:r)';
    ratings_pred2 = max(1, min(5, ratings_pred2));
    
    % 计算误差
    train_rmse2 = sqrt(mean((ratings_pred2(mask) - ratings_true(mask)).^2));
    test_rmse2 = sqrt(mean((ratings_pred2(~mask) - ratings_true(~mask)).^2));
    
    % 与简单方法比较
    simple_pred = U1(:, 1:r) * S1(1:r, 1:r) * V1(:, 1:r)';
    simple_pred = max(1, min(5, simple_pred));
    simple_test_rmse = sqrt(mean((simple_pred(~mask) - ratings_true(~mask)).^2));
    
    improvement = (simple_test_rmse - test_rmse2) / simple_test_rmse * 100;
    
    fprintf('%2d    %9.4f    %8.4f    %7.1f%%\n', r, train_rmse2, test_rmse2, improvement);
end

%% 实验4：用户相似性分析
fprintf('\n实验4：用户相似性分析\n');
fprintf('目标：分析用户之间的相似性\n\n');

% 使用最佳秩进行分析
best_rank = 10;
U_best = U2(:, 1:best_rank);
S_best = S2(1:best_rank, 1:best_rank);

% 用户特征向量
user_features = U_best * sqrt(S_best);

% 计算用户相似性矩阵
user_similarity = user_features * user_features';

% 分析相似性分布
similarity_values = user_similarity(triu(true(n_users), 1));
fprintf('用户相似性统计:\n');
fprintf('平均相似性: %.4f\n', mean(similarity_values));
fprintf('相似性标准差: %.4f\n', std(similarity_values));
fprintf('最高相似性: %.4f\n', max(similarity_values));
fprintf('最低相似性: %.4f\n', min(similarity_values));

% 找到最相似的用户对
[max_sim, max_idx] = max(similarity_values);
[user1, user2] = find(user_similarity == max_sim, 1);
if user1 == user2
    user_similarity_temp = user_similarity;
    user_similarity_temp(logical(eye(n_users))) = -inf;
    [max_sim, max_idx] = max(user_similarity_temp(:));
    [user1, user2] = ind2sub(size(user_similarity_temp), max_idx);
end

fprintf('最相似用户对: 用户%d 和 用户%d (相似性: %.4f)\n', user1, user2, max_sim);

% 分析这两个用户的评分模式
user1_ratings = ratings_observed(user1, :);
user2_ratings = ratings_observed(user2, :);
common_items = mask(user1, :) & mask(user2, :);

if sum(common_items) > 0
    fprintf('共同评分物品数: %d\n', sum(common_items));
    fprintf('用户%d平均评分: %.2f\n', user1, mean(user1_ratings(common_items)));
    fprintf('用户%d平均评分: %.2f\n', user2, mean(user2_ratings(common_items)));
    correlation = corr(user1_ratings(common_items)', user2_ratings(common_items)');
    fprintf('评分相关性: %.4f\n', correlation);
end

%% 实验5：物品推荐生成
fprintf('\n实验5：物品推荐生成\n');
fprintf('目标：为用户生成个性化推荐\n\n');

% 选择一个测试用户
test_user = 1;
user_ratings = ratings_observed(test_user, :);
user_mask = mask(test_user, :);

fprintf('测试用户信息:\n');
fprintf('用户ID: %d\n', test_user);
fprintf('已评分物品数: %d\n', sum(user_mask));
fprintf('平均评分: %.2f\n', mean(user_ratings(user_mask)));

% 使用SVD预测评分
predicted_ratings = U2(test_user, 1:best_rank) * S2(1:best_rank, 1:best_rank) * V2(:, 1:best_rank)';
predicted_ratings = max(1, min(5, predicted_ratings));

% 找到未评分的物品
unrated_items = find(~user_mask);
unrated_predictions = predicted_ratings(unrated_items);

% 生成推荐列表
[sorted_predictions, sort_idx] = sort(unrated_predictions, 'descend');
recommended_items = unrated_items(sort_idx);

fprintf('\nTop 10 推荐物品:\n');
fprintf('排名    物品ID    预测评分    真实评分    误差\n');
fprintf('----    ------    --------    --------    ----\n');

for i = 1:min(10, length(recommended_items))
    item_id = recommended_items(i);
    pred_rating = sorted_predictions(i);
    true_rating = ratings_true(test_user, item_id);
    error = abs(pred_rating - true_rating);
    
    fprintf('%4d    %6d    %8.2f    %8.2f    %.2f\n', ...
            i, item_id, pred_rating, true_rating, error);
end

% 推荐质量评估
top_k = 5;
top_k_items = recommended_items(1:top_k);
top_k_true_ratings = ratings_true(test_user, top_k_items);
top_k_pred_ratings = sorted_predictions(1:top_k);

fprintf('\nTop-%d推荐质量:\n', top_k);
fprintf('平均预测评分: %.2f\n', mean(top_k_pred_ratings));
fprintf('平均真实评分: %.2f\n', mean(top_k_true_ratings));
fprintf('预测准确度(RMSE): %.3f\n', sqrt(mean((top_k_pred_ratings - top_k_true_ratings).^2)));

%% 实验6：冷启动问题
fprintf('\n实验6：冷启动问题\n');
fprintf('目标：分析新用户和新物品的推荐问题\n\n');

% 模拟新用户（只有很少评分）
new_user_ratings = zeros(1, n_items);
n_new_ratings = 3;  % 新用户只有3个评分
rated_items = randperm(n_items, n_new_ratings);
new_user_ratings(rated_items) = ratings_true(1, rated_items) + 0.2*randn(1, n_new_ratings);
new_user_ratings = max(1, min(5, new_user_ratings));

fprintf('新用户冷启动分析:\n');
fprintf('新用户评分数: %d\n', n_new_ratings);
fprintf('新用户平均评分: %.2f\n', mean(new_user_ratings(rated_items)));

% 方法1：使用物品平均评分
item_avg_predictions = item_means';
cold_start_rmse1 = sqrt(mean((item_avg_predictions(~(new_user_ratings > 0)) - ...
                              ratings_true(1, ~(new_user_ratings > 0))).^2));

% 方法2：基于物品相似性
item_features = V2(:, 1:best_rank) * sqrt(S2(1:best_rank, 1:best_rank));
item_similarity = item_features * item_features';

% 为新用户预测评分
similarity_predictions = zeros(1, n_items);
for i = 1:n_items
    if new_user_ratings(i) == 0  % 未评分物品
        % 找到相似物品
        similarities = item_similarity(i, :);
        rated_mask = new_user_ratings > 0;
        
        if sum(rated_mask) > 0
            weighted_sum = sum(similarities(rated_mask) .* new_user_ratings(rated_mask));
            similarity_sum = sum(abs(similarities(rated_mask)));
            
            if similarity_sum > 0
                similarity_predictions(i) = weighted_sum / similarity_sum;
            else
                similarity_predictions(i) = item_means(i);
            end
        else
            similarity_predictions(i) = item_means(i);
        end
    end
end

cold_start_rmse2 = sqrt(mean((similarity_predictions(~(new_user_ratings > 0)) - ...
                              ratings_true(1, ~(new_user_ratings > 0))).^2));

fprintf('冷启动预测方法比较:\n');
fprintf('物品平均评分方法 RMSE: %.3f\n', cold_start_rmse1);
fprintf('物品相似性方法 RMSE: %.3f\n', cold_start_rmse2);
fprintf('相似性方法改善: %.1f%%\n', (cold_start_rmse1 - cold_start_rmse2) / cold_start_rmse1 * 100);

%% 实验7：推荐系统评估指标
fprintf('\n实验7：推荐系统评估指标\n');
fprintf('目标：计算各种推荐系统评估指标\n\n');

% 使用最佳模型进行全面评估
final_predictions = U2(:, 1:best_rank) * S2(1:best_rank, 1:best_rank) * V2(:, 1:best_rank)';
final_predictions = max(1, min(5, final_predictions));

% 1. RMSE (Root Mean Square Error)
test_rmse_final = sqrt(mean((final_predictions(~mask) - ratings_true(~mask)).^2));

% 2. MAE (Mean Absolute Error)  
test_mae = mean(abs(final_predictions(~mask) - ratings_true(~mask)));

% 3. 覆盖率 (Coverage)
coverage_final = mean(any(final_predictions > 0, 1));

% 4. 精确度和召回率（基于阈值）
threshold = 4.0;  % 评分阈值
true_positives = sum((final_predictions(~mask) >= threshold) & (ratings_true(~mask) >= threshold));
false_positives = sum((final_predictions(~mask) >= threshold) & (ratings_true(~mask) < threshold));
false_negatives = sum((final_predictions(~mask) < threshold) & (ratings_true(~mask) >= threshold));

precision = true_positives / (true_positives + false_positives);
recall = true_positives / (true_positives + false_negatives);
f1_score = 2 * precision * recall / (precision + recall);

fprintf('推荐系统评估结果:\n');
fprintf('RMSE: %.4f\n', test_rmse_final);
fprintf('MAE: %.4f\n', test_mae);
fprintf('覆盖率: %.2f%%\n', coverage_final * 100);
fprintf('精确度: %.4f\n', precision);
fprintf('召回率: %.4f\n', recall);
fprintf('F1分数: %.4f\n', f1_score);

fprintf('\n=== 推荐系统实验总结 ===\n');
fprintf('1. SVD可以有效进行协同过滤推荐\n');
fprintf('2. 填充策略对推荐质量有重要影响\n');
fprintf('3. 用户和物品的潜在因子揭示了偏好模式\n');
fprintf('4. 相似性分析有助于理解用户行为\n');
fprintf('5. 冷启动问题需要特殊处理策略\n');
fprintf('6. 多种评估指标全面衡量推荐质量\n');
fprintf('7. SVD方法简单有效，适合中等规模数据\n\n');

end